package auth

import (
	"encoding/json"
	"github.com/dgrijalva/jwt-go"
	"time"
	"zong-microservice/app/models"
	"zong-microservice/pkg/cache"
	"zong-microservice/pkg/config"
	"zong-microservice/pkg/helper"
	"zong-microservice/pkg/logger"
)

// GetToken 获取 token
func GetToken(user models.User) string {
	// 超时时间戳（秒）
	expires := int64(helper.StringToInt(config.Get("jwt", "expires")) * 60)
	// 过期时间戳（秒）: 当前时间戳（秒） + 超时时间戳（秒）
	expiresTime := time.Now().Unix() + expires

	claims := jwt.StandardClaims{
		Audience:  user.Username,      // 受众
		ExpiresAt: expiresTime,        // 失效时间
		Id:        user.GetStringID(), // 编号
		IssuedAt:  time.Now().Unix(),  // 签发时间
		Issuer:    "zong-microservice",          // 签发人
		NotBefore: time.Now().Unix(),  // 生效时间
		Subject:   "login",            // 主题
	}

	tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	token, err := tokenClaims.SignedString([]byte(config.Get("jwt", "secret")))
	logger.LogError(err)
	token = "Bearer " + token

	// 存入 redis 缓存
	userByte, _ := json.Marshal(user) // json序列化
	cache.Set("UserCache_"+user.GetStringID(), userByte, expires)

	return token
}

// ParseToken 验证 token
func ParseToken(token string) (*jwt.StandardClaims, error) {
	jwtToken, err := jwt.ParseWithClaims(token, &jwt.StandardClaims{}, func(token *jwt.Token) (i interface{}, e error) {
		return []byte(config.Get("jwt", "secret")), nil
	})
	if err == nil && jwtToken != nil {
		if claim, ok := jwtToken.Claims.(*jwt.StandardClaims); ok && jwtToken.Valid {
			return claim, nil
		}
	}
	return nil, err
}

// RefreshToken 刷新 token
func RefreshToken(authorization string, user models.User) string {
	token, _ := ParseToken(authorization)
	id := uint64(helper.StringToInt(token.Id))

	if u, err := user.GetByID(id); err != nil {
		logger.LogError(err)
		return ""
	} else {
		return GetToken(u)
	}
}

// FlushToken 删除 token 实际是刷新 token 但是不返回
func FlushToken(authorization string, user models.User) {
	token, _ := ParseToken(authorization)
	id := uint64(helper.StringToInt(token.Id))

	if u, err := user.GetByID(id); err != nil {
		logger.LogError(err)
	} else {
		GetToken(u)
		// 删除 redis 缓存
		cache.Del("UserCache_" + u.GetStringID())
	}
}
